%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lex.h"

#define YYDEBUG 1
#define YYERROR_VERBOSE

void error(char *fmt, ...);
void yyerror(char *msg);
%}
/*
   Bison declarations
*/
%union {
	char *str;
	int integer;
	int boolean;
}

%token FUNCTION	
%token ENDFUNCTION	
%token MAIN
%token VAR
%token ADD
%token MULT
%token LABEL 
%token AND
%token OR
%token NOT
%token MOVE
%token IFZERO 
%token IFTRUE 
%token IFFALSE
%token IFGREATER
%token IFLESS 
%token IFEQUAL 
%token GOTO 
%token CALL
%token READ
%token WRITE
%token RETURN
%token IFNZERO
%token SKIP
%token RESTORE
%token SETPARAM
%token TRUE 
%token FALSE 
%token REF
%token VAL
%token RES
%token VALRES 
%token PARAM 
%token ERROR_TOKEN

%token <str> STRING 
%token NAME
%token <integer> INTEGER 
%token NUMBER
%token <boolean> BOOLEAN
/*
%token <str> STRING NAME
%token <integer> INTEGER NUMBER
%token <boolean> BOOLEAN
*/
%token DIGIT true false
/*
%type <str> 	STRING
%type <integer> INTEGER
%type <boolean> BOOLEAN
*/

%%
/*
   Bison grammar rules
*/
programa
		:decl_vars decl_main decl_funcoes
		;

decl_vars
		: /* Empty */
		| decl_var decl_vars 
		| error 
		;

decl_var
		: VAR tipo nome
		| error 
		;

decl_main
		: MAIN decl_codigo
		| error 
		;

decl_funcoes
		: /* Empty */
		| decl_funcao decl_funcoes
		| error 
		;

decl_funcao
		: FUNCTION nome tipo decl_params decl_vars decl_funcoes decl_codigo ENDFUNCTION
		| error
		;

decl_params
		: /* Empty */
		| decl_param decl_params
		| error
		;

decl_param
		: PARAM tipo_passagem tipo nome
		;

tipo_passagem
		: REF
		| VAL
		| RES
		| VALRES
		| error
		;

tipo
		: INTEGER
		| STRING
		| BOOLEAN
		| error 
		;

decl_codigo
		: op_aritm
		| op_logica
		| decl_codigo decl_codigo
		| ref_label
		| cmd_saltocond
		| cmd_saltoincond
		| cmd_chamada
		| cmd_io
		| cmd_retorno
		| cmd_skip
		| cmd_valorretorno
		| cmd_paramreal
		| cmd_atrib
		| error
		;

ref_label
		: LABEL nome
		;

op_aritm
		: ADD numero nome
		| ADD nome nome
		| MULT numero nome
		| MULT nome nome
		;

op_logica
		: AND nome nome
		| OR nome nome
		| NOT nome
		;

cmd_atrib
		: MOVE literal nome
		| MOVE nome nome
		;

cmd_saltocond
		: IFZERO nome nome
		| IFNZERO nome nome
		| IFTRUE nome nome
		| IFFALSE nome nome
		| IFGREATER nome nome nome
		| IFLESS nome nome nome
		| IFEQUAL nome nome nome
		;

cmd_saltoincond
		: GOTO nome
		;

cmd_chamada
		: CALL nome
		;

cmd_io
		: READ nome
		| WRITE nome
		| WRITE literal
		;

cmd_retorno
		: RETURN nome
		| RETURN literal
		;

cmd_skip
		: SKIP
		;

cmd_valorretorno
		: RESTORE nome
		;

cmd_paramreal
		: SETPARAM nome
		| SETPARAM literal
		;

literal
		: NAME
		| NUMBER
		| true
		| false
		| valor
		| error
		;

valor
		: numero
		| error
		;

numero
		: DIGIT
		| DIGIT NUMBER
		;

nome
		: NAME
		| literal
		| error
		;


%%
/*
   Aditional code
*/
